#load "parser.cmo";;
#load "scanner.cmo";;
#use "ast.mli";;
#use "testlib.ml";;

addtest "DeclarationParsing"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "integer a;"))
        ([Ast.Declare (Ast.Type_int,"a")]);;

addtest "AssignmentParsing"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "a <- 5;"))
        ([ Ast.Expr(Ast.Assign ((Ast.IdVar "a"),(Ast.Literal (Ast.Literal_int 5)))) ] );;

addtest "ArithmeticParsing"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "1 + 5;"))
        ([ Ast.Expr(Ast.Binop ((Ast.Literal (Ast.Literal_int 1)),
                      Ast.Add,
                      (Ast.Literal (Ast.Literal_int 5))))] );;

addtest "NestedExpressionParsing"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "a <- 1 + 5;"))
        ([Ast.Expr(Ast.Assign ((Ast.IdVar "a"),
                       (Ast.Binop ((Ast.Literal (Ast.Literal_int 1)),
                                   Ast.Add,
                                   (Ast.Literal (Ast.Literal_int 5))))))] );;

addtest "SequentialExpressionParsing"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "integer a; a <- 1;"))
        ([Ast.Declare (Ast.Type_int,"a");
          Ast.Expr (Ast.Assign ((Ast.IdVar "a"),(Ast.Literal (Ast.Literal_int 1))))]);;

addtest "FunctionDeclarationParsing"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "function foo () -> integer {return 5;}"))
        ([Ast.FuncDecl ("foo",[],Ast.Type_int,Ast.Block [(Ast.Return (Ast.Literal (Ast.Literal_int 5)))])]);;

addtest "FunctionDeclarationParsingWithArgs"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "function foo (integer x, integer y) -> integer {return 5;}"))
        ([Ast.FuncDecl ("foo",[(Ast.Type_int, "x"); (Ast.Type_int, "y")],Ast.Type_int,Ast.Block [(Ast.Return (Ast.Literal (Ast.Literal_int 5)))])]);;

addtest "FunctionCallParsing"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "print(5);"))
        ([Ast.Expr (Ast.Call ("print", [(Ast.Literal (Ast.Literal_int 5))]))]);;

(*
addtest "StructDeclareParsing"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "struct foo {};"))
        ( [ Ast.DeclareStruct("foo",Ast.Block([])) ] );;

addtest "StructDeclareParsingWithInt"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "struct foo {integer a;};"))
        ( [ Ast.DeclareStruct("foo",Ast.Block([Ast.Expr(Ast.Declare ("integer","a"))])) ] );;

addtest "StructDeclareVariable"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "struct foo myvar;"))
        ( [ Ast.Expr( Ast.Struct("foo","myvar")) ] );;
*)

addtest "ArrayDeclareParsing"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "integer[5] intArr;"))
        ([Ast.Declare( Ast.Type_Array(Ast.Type_int, 5), "intArr")]);;

addtest "MapDeclareParsing"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "integer[[string]] strMap;"))
        ([Ast.Declare( Ast.Type_Map(Ast.Type_int, Ast.Type_str), "strMap")]);;

addtest "TestArrayLiteral"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "a <- array {5,2};"))
        ([ Ast.Expr(Ast.Assign(Ast.IdVar("a"),Ast.Literal(Ast.Literal_array([Ast.Literal_int 5; Ast.Literal_int 2])))) ]);;

addtest "TestArrayLiteralEmpty"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "a <- array {};"))
        ([ Ast.Expr(Ast.Assign(Ast.IdVar("a"),Ast.Literal(Ast.Literal_array([]))))]);;

addtest "TestMapLiteralInt"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "a <- map { 5->1, 2->0};" ))
        ([Ast.Expr(Ast.Assign(Ast.IdVar("a"),
                   Ast.Literal(Ast.Literal_map([(Ast.Literal_int 5,
                                                 Ast.Literal_int 1);
                                                (Ast.Literal_int 2,
                                                 Ast.Literal_int 0)
                                               ]))))]);;

addtest "TestMapLiteralEmpty"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "a <- map {};" ))
        ([Ast.Expr(Ast.Assign(Ast.IdVar("a"),
                   Ast.Literal(Ast.Literal_map([]))))]);;

(*
addtest "StructAssignReference"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "a.b <- c.d;" ))
        ([ Ast.Expr( Ast.Assign( Ast.Structref("a","b"), Ast.Var(Ast.Structref("c","d")) ) ) ]);;
*)

addtest "ArrayAssignReference"
        (function () -> Parser.program Scanner.token
                        (Lexing.from_string "a[0] <- a[1];" ))
        ([ Ast.Expr(Ast.Arrayassign(Ast.IdVar("a"),
                                    Ast.Literal(Ast.Literal_int(0)),
                                    Ast.Arrayref(Ast.IdVar("a"),Ast.Literal(Ast.Literal_int(1)))))]);;



runtests();;
